home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / comstr.exe / COMSTREA.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-03  |  11.3 KB  |  599 lines

  1. #if !defined( __DOS_H )
  2. #include <Dos.h>
  3. #endif    // __DOS_H
  4.  
  5. #if !defined( __COMSTREAM_H )
  6. #include "Comstream.h"
  7. #endif    // __COMSTREAM_H
  8.  
  9. #if !defined( __TIMER_H )
  10. #include "Timer.h"
  11. #endif    // __TIMER_H
  12.  
  13. #define TESTPORTBIT(x,y) (inportb(x) & y)
  14.  
  15. #define IER    1
  16. #define IIR    2
  17. #define LCR    3
  18. #define LSR    5
  19. #define MSR    6
  20.  
  21. #define    MODEMFAIL    0
  22. #define XMTEMPTY    2
  23. #define READFULL    4
  24. #define LINEFAIL    6
  25.  
  26. #define    RXRDY        1
  27. #define TBE            32
  28. #define TXE            64
  29.  
  30. #define RTS            2
  31. #define GP01        4
  32. #define GP02        8
  33. #define    LOOPBACK    16
  34.  
  35. #define CTS            16
  36.  
  37. #define DLAB        128
  38.  
  39. ComDef::ComDef( int n )
  40.     {
  41.     if( n >= 0 && n < 4 )
  42.         {
  43.         unsigned far *pPort = (unsigned far *) MK_FP( 0, 0x400 );
  44.         portAddr = pPort[n];
  45.         }
  46.     else
  47.         portAddr = 0;
  48.  
  49.     if( portAddr != 0 )
  50.         {
  51.         irqAddr = ( n & 1 ) ? 0x0B : 0x0C;
  52.         picMask = ( n & 1 ) ? 0x08 : 0x10;
  53.         oldhandler = getvect( irqAddr );
  54.         }
  55.     else
  56.         {
  57.         irqAddr = picMask = 0;
  58.         oldhandler = 0;
  59.         }
  60.     owner = 0;
  61.     }
  62.  
  63. ComDef::~ComDef()
  64.     {
  65.     clrCombuf();
  66.     }
  67.  
  68. void ComDef::setParams( int aPort, int aIRQ, int aMask )
  69.     {
  70.     if( owner != 0 )    return;
  71.  
  72.     if( oldhandler && irqAddr )
  73.         setvect( irqAddr, oldhandler );
  74.     oldhandler = 0;
  75.  
  76.     portAddr = aPort;
  77.     irqAddr = aIRQ;
  78.     picMask = aMask;
  79.     oldhandler = getvect( irqAddr );
  80.     }
  81.  
  82. int ComDef::setCombuf( combuf *cb )
  83.     {
  84.     void interrupt far (*handler)(...);
  85.  
  86.     if( owner != 0 )    return 0;
  87.  
  88.     if( irqAddr == 0x0B )
  89.         handler = combuf::handler0x0B;
  90.     else if( irqAddr == 0x0C )
  91.         handler = combuf::handler0x0C;
  92.     else
  93.         return 0;
  94.  
  95.     owner = cb;
  96.     outportb( portAddr+MCR, 0 );
  97.     outportb( portAddr+IER, 0 );
  98.     outportb( portAddr+LCR, inportb(portAddr+LCR) & 0x3F );
  99.     for( int i = 0; i < 7; i++ )
  100.         inportb( portAddr+i );
  101.     setvect( irqAddr, handler );
  102.     outportb( 0x21, (inportb(0x21) & ~picMask) );
  103.     outportb( portAddr+MCR, GP02 );
  104.     outportb( portAddr+IER, 0x0F );
  105.     return 1;
  106.     }
  107.  
  108. void ComDef::clrCombuf()
  109.     {
  110.     if( owner == 0 )    return;
  111.     if( irqAddr != 0x0B && irqAddr != 0x0C )
  112.         return;
  113.     outportb( 0x21, (inportb(0x21) | picMask) );
  114.     outportb( portAddr+MCR, 0 );
  115.     outportb( portAddr+IER, 0 );
  116.     setvect( irqAddr, oldhandler );
  117.     owner = 0;
  118.     }
  119.  
  120. ComDef combuf::def[] = { 0, 1, 2, 3 };
  121.  
  122. void interrupt far combuf::handler0x0B(...)
  123.     {
  124.     combuf *owner;
  125.     int i, port, cause, data;
  126.  
  127.     for( i = 0; i < NUMBEROFPORTS; i++ )
  128.         if( (owner = combuf::def[i].owner) != 0 && combuf::def[i].irqAddr == 0x0B )
  129.             {
  130.             port = combuf::def[i].portAddr;
  131.             cause = inportb( port+IIR ) & 0x0F;
  132.             if( (cause & 1) == 0 )
  133.                 {
  134.                 if( cause == READFULL )            data = inportb( port );
  135.                 else if( cause == LINEFAIL )    data = inportb( port+LSR );
  136.                 else if( cause == MODEMFAIL )    data = inportb( port+MSR );
  137.                 outportb( 0x20, 0x20 );
  138.                 owner->handleIRQ( port, cause, data );
  139.                 return;
  140.                 }
  141.             }
  142.     outportb( 0x20, 0x20 );
  143.     }
  144.  
  145.  
  146. void interrupt far combuf::handler0x0C(...)
  147.     {
  148.     combuf *owner;
  149.     int i, port, cause, data;
  150.  
  151.     for( i = 0; i < NUMBEROFPORTS; i++ )
  152.         if( (owner = combuf::def[i].owner) != 0 && combuf::def[i].irqAddr == 0x0C )
  153.             {
  154.             port = combuf::def[i].portAddr;
  155.             cause = inportb( port+IIR ) & 0x0F;
  156.             if( (cause & 1) == 0 )
  157.                 {
  158.                 if( cause == READFULL )            data = inportb( port );
  159.                 else if( cause == LINEFAIL )    data = inportb( port+LSR );
  160.                 else if( cause == MODEMFAIL )    data = inportb( port+MSR );
  161.                 outportb( 0x20, 0x20 );
  162.                 owner->handleIRQ( port, cause, data );
  163.                 return;
  164.                 }
  165.             }
  166.     outportb( 0x20, 0x20 );
  167.     }
  168.  
  169. void combuf::handleIRQ( int port, int cause, int data )
  170.     {
  171.     if( cause == READFULL )
  172.         insertc( data );
  173.     else if( cause == XMTEMPTY )
  174.         {
  175.         int ch = extractc();
  176.         if( ch != EOF )
  177.             {
  178.             if( ibdelay_ != 0 || (ch == '\r' && ildelay_ != 0) )
  179.                 {
  180.                 long l = (ch == '\r' && ildelay_ != 0) ? ildelay_ : ibdelay_;
  181.                 int n = inportb( 0x21 );
  182.                 outportb( 0x21, n | 0x18 );
  183.                 enable();
  184.                 Timer timer;
  185.                 while( timer.elapsed() < l );
  186.                 disable();
  187.                 outportb( 0x21, n );
  188.                 }
  189.             outportb( port, ch );
  190.             }
  191.         }
  192.     else if( cause == LINEFAIL )
  193.         errFlags |= ( data & (OR | FE | PE | BI) );
  194.     }
  195.  
  196. combuf::combuf( char *b, int inlen, int outlen ) : streambuf( b, inlen+outlen )
  197.     {
  198.     inSize = inlen;
  199.     errFlags = 0;
  200.     options = 0;
  201.     offs_ = EOF;
  202.     setTimeout( 300 );
  203.     setInterCharDelay( 0 );
  204.     setInterLineDelay( 0 );
  205.     }
  206.  
  207. combuf::combuf()
  208.     {
  209.     inSize = 0;
  210.     errFlags = 0;
  211.     options = 0;
  212.     offs_ = EOF;
  213.     setTimeout( 300 );
  214.     setInterCharDelay( 0 );
  215.     setInterLineDelay( 0 );
  216.     }
  217.  
  218. combuf::~combuf()
  219.     {
  220.     setPort();
  221.     }
  222.  
  223. streambuf *combuf::setbuf( signed char *b, int len )
  224.     {
  225.     streambuf::setbuf( b, len );
  226.     inSize = len/2;
  227.     return this;
  228.     }
  229.  
  230. combuf *combuf::setbuf( char *b, int inlen, int outlen )
  231.     {
  232.     streambuf::setbuf( b, inlen+outlen );
  233.     inSize = inlen;
  234.     return this;
  235.     }
  236.  
  237. int combuf::underflow()
  238.     {
  239.     Timer timer;
  240.  
  241.     if( offs_ == EOF )    return EOF;
  242.  
  243.     if( in_avail() == 0 )
  244.         {
  245.         while( timer.elapsed() < timeout_ && in_avail() == 0 );
  246.         if( in_avail() == 0 )
  247.             {
  248.             errFlags |= TIMEOUT;
  249.             return EOF;
  250.             }
  251.         }
  252.     return (unsigned char) *(gptr());
  253.     }
  254.  
  255. int combuf::do_sputn( const char *b, int len )
  256.     {
  257.     Timer timer;
  258.     long l;
  259.     int i, port, n;
  260.  
  261.     if( offs_ == EOF || base() == 0 || len <= 0)
  262.         return 0;
  263.  
  264.     if( pptr() == 0 )
  265.         {
  266.         port = def[offs_].portAddr;
  267.         if( (options & HW_HANDSHAKE) != 0 )
  268.             assertToPort( MCR, RTS );
  269.         if( ibdelay_ != 0 || (*b == '\r' && ildelay_ != 0) )
  270.             {
  271.             l = (*b == '\r' && ildelay_ != 0) ? ildelay_ : ibdelay_;
  272.             timer.start();
  273.             while( timer.elapsed() < l );
  274.             }
  275.  
  276.         timer.start();
  277.         while( TESTPORTBIT(port+LSR,TBE) == 0 &&
  278.                 ( (options & HW_HANDSHAKE) == 0 || TESTPORTBIT(port+MSR,CTS) != 0 ) )
  279.             if( timer.elapsed() >= timeout_ )
  280.                 {
  281.                 errFlags |= TIMEOUT;
  282.                 return 0;
  283.                 }
  284.  
  285.         if( len == 1 )
  286.             {
  287.             outportb( port, *b );
  288.             return 1;
  289.             }
  290.  
  291.         n = blen()-inSize;
  292.         setp( base()+inSize, ebuf() );
  293.         if( n >= len-1 )
  294.             {
  295.             memcpy( pptr(), b+1, len-1 );
  296.             pbump( len-1 );
  297.             outportb( port, *b );
  298.             return len;
  299.             }
  300.  
  301.         memcpy( pptr(), b+1, n );
  302.         pbump( n );
  303.         outportb( port, *b );
  304.         b += (n+1);
  305.         for( i = n+1; i < len && sputc(*b++) != EOF; i++ )
  306.             i++;
  307.         return i;
  308.         }
  309.     else
  310.         return streambuf::do_sputn( b, len );
  311.     }
  312.  
  313. int combuf::overflow( int c )
  314.     {
  315.     char b = c;
  316.     return do_sputn( &b, 1 );
  317.     }
  318.  
  319. void combuf::setBaud( long baud )
  320.     {
  321.     if( offs_ == EOF || baud < 50 || baud > 115200L )
  322.         return;
  323.     unsigned u = (unsigned) ( 115200L / baud );
  324.     assertToPort( LCR, DLAB );
  325.     outportb( def[offs_].portAddr, (u & 0xFF) );
  326.     outportb( def[offs_].portAddr+1, ((u >> 8) & 0xFF) );
  327.     unassertToPort( LCR, DLAB );
  328.     }
  329.  
  330. void combuf::setParity( int parity )
  331.     {
  332.     int i;
  333.  
  334.     if( offs_ == EOF )    return;
  335.     else if( parity == NO_PARITY )        i = 0;
  336.     else if( parity == ODD_PARITY )     i = 0x08;
  337.     else if( parity == EVEN_PARITY )    i = 0x18;
  338.     else    return;
  339.     outportb( def[offs_].portAddr+LCR, (inportb(def[offs_].portAddr+LCR) & 0xC7) | i );
  340.     }
  341.  
  342. void combuf::setBits( int bits )
  343.     {
  344.     if( offs_ == EOF || bits < 6 || bits > 8 )    return;
  345.     bits -= 5;
  346.     outportb( def[offs_].portAddr+LCR, (inportb(def[offs_].portAddr+LCR) & 0xFC) | bits );
  347.     }
  348.  
  349. void combuf::setStopBits( int bits )
  350.     {
  351.     if( offs_ == EOF || bits < 1 || bits > 2 )    return;
  352.     bits = (bits-1)*4;
  353.     outportb( def[offs_].portAddr+LCR, (inportb(def[offs_].portAddr+LCR) & 0xFB) | bits );
  354.     }
  355.  
  356. void combuf::setParams( CommProtocol& p )
  357.     {
  358.     if( offs_ == EOF )    return;
  359.     if( p.baud < 50L || p.baud > 115200L )    return;
  360.     if( p.parity < NO_PARITY || p.parity > EVEN_PARITY )    return;
  361.     if( p.bits < 6 || p.bits > 8 )    return;
  362.     if( p.stopBits != 1 && p.stopBits != 2 )    return;
  363.  
  364.     setBaud( p.baud );
  365.     setParity( p.parity );
  366.     setBits( p.bits );
  367.     setStopBits( p.stopBits );
  368.     }
  369.  
  370. void combuf::setTimeout( unsigned long l )
  371.     {
  372.     timeout_ = timeToTicks( l );
  373.     }
  374.  
  375. void combuf::setInterCharDelay( unsigned long l )
  376.     {
  377.     ibdelay_ = timeToTicks( l );
  378.     }
  379.  
  380. void combuf::setInterLineDelay( unsigned long l )
  381.     {
  382.     ildelay_ = timeToTicks( l );
  383.     }
  384.  
  385. void combuf::setPort( int p )
  386.     {
  387.     if( offs_ != EOF )
  388.         def[offs_].clrCombuf();
  389.     if( p < 0 || p > 3  || blen() == 0 )
  390.         p = EOF;
  391.     offs_ = p;
  392.     if( offs_ != EOF )
  393.         {
  394.         for( int i = 0; i < NUMBEROFPORTS; i++ )
  395.             {
  396.             if( i == p )    continue;
  397.             if( def[i].owner != 0 )
  398.                 if( def[i].portAddr == def[p].portAddr ||
  399.                     def[i].irqAddr == def[p].irqAddr ||
  400.                     def[i].picMask == def[p].picMask )
  401.                     break;
  402.             }
  403.         if( i < NUMBEROFPORTS )
  404.             offs_ = EOF;
  405.  
  406.         else if( def[offs_].setCombuf( this ) == 0 )
  407.             offs_ = EOF;
  408.         else
  409.             {
  410.             setg( base(), base(), base() );
  411.             setp( 0, 0 );
  412.             }
  413.         }
  414.     errFlags = 0;
  415.     }
  416.  
  417. int combuf::extractc()
  418.     {
  419.     Timer timer;
  420.     int n, ch;
  421.  
  422.     if( (n = out_waiting()) != 0 )
  423.         {
  424.         char *pb = pbase();
  425.         ch = *pb;
  426.         if( n > 1 )
  427.             {
  428.             pb++;
  429.             setp( pb, epptr() );
  430.             pbump(n-1);
  431.             }
  432.         else
  433.             setp( 0, 0 );
  434.         }
  435.     else
  436.         {
  437.         setp( 0, 0 );
  438.         ch = EOF;
  439.         }
  440.     return ch;
  441.     }
  442.  
  443. int combuf::insertc( int c )
  444.     {
  445.     if( egptr() < base()+inSize )
  446.         {
  447.         *(egptr()) = c;
  448.         setg( base(), gptr(), egptr()+1 );
  449.         }
  450.     else if( gptr() > base() )
  451.         {
  452.         int len = (int)(egptr() - gptr());
  453.         memmove( base(), gptr(), len );
  454.         *(base()+len) = c;
  455.         setg( base(), base(), base()+len+1 );
  456.         }
  457.     else
  458.         {
  459.         errFlags |= OR;
  460.         return EOF;
  461.         }
  462.     return c;
  463.     }
  464.  
  465. unsigned long combuf::timeToTicks( unsigned long l )
  466.     {
  467.     return l * 182L / 1000L;
  468.     }
  469.  
  470. void combuf::assertToPort( int o, int mask )
  471.     {
  472.     outportb( def[offs_].portAddr+o, (inportb(def[offs_].portAddr+o) | mask) );
  473.     }
  474.  
  475. void combuf::unassertToPort( int o, int mask )
  476.     {
  477.     outportb( def[offs_].portAddr+o, (inportb(def[offs_].portAddr+o) & ~mask) );
  478.     }
  479.  
  480. comstream::comstream() : buf()
  481.     {
  482.     ios::init(&buf);
  483.     }
  484.  
  485. comstream::comstream( char *cbuf, int isz, int osz ) :
  486.     buf( cbuf, isz, osz )
  487.     {
  488.     ios::init(&buf);
  489.     }
  490.  
  491. comstream::~comstream()
  492.     {
  493.     }
  494.  
  495. void comstream::open( int aPort )
  496.     {
  497.     if( buf.offs_ != EOF )
  498.         clear(ios::failbit);
  499.     else
  500.         {
  501.         buf.setPort(aPort);
  502.         if( buf.offs_ != EOF )
  503.             {
  504.             clear(ios::goodbit);
  505.             buf.assertDTR();
  506.             }
  507.         else
  508.             clear(ios::badbit);
  509.         }
  510.     }
  511.  
  512. void comstream::close()
  513.     {
  514.     buf.setPort();
  515.     if( buf.offs_ == EOF )
  516.         clear(ios::goodbit);
  517.     else
  518.         setstate(ios::failbit);
  519.     }
  520.  
  521.  
  522. static comstream& sbd( comstream& o, long b )
  523.     {
  524.     o.rdbuf()->setBaud(b);
  525.     return o;
  526.     }
  527.  
  528. ComManipLong baud( long b )
  529.     {
  530.     return ComManipLong( sbd, b );
  531.     }
  532.  
  533. static comstream& sbit( comstream& o, int b )
  534.     {
  535.     o.rdbuf()->setBits(b);
  536.     return o;
  537.     }
  538.  
  539. ComManipInt bits( int b )
  540.     {
  541.     return ComManipInt( sbit, b );
  542.     }
  543.  
  544. static comstream& spty( comstream& o, int b )
  545.     {
  546.     o.rdbuf()->setParity(b);
  547.     return o;
  548.     }
  549.  
  550. ComManipInt parity( int b )
  551.     {
  552.     return ComManipInt( spty, b );
  553.     }
  554.  
  555. static comstream& ssbit( comstream& o, int b )
  556.     {
  557.     o.rdbuf()->setStopBits(b);
  558.     return o;
  559.     }
  560.  
  561. ComManipInt stopbits( int b )
  562.     {
  563.     return ComManipInt( ssbit, b );
  564.     }
  565.  
  566. static comstream& sto( comstream& o, long t )
  567.     {
  568.     o.rdbuf()->setTimeout(t);
  569.     return o;
  570.     }
  571.  
  572. ComManipLong timeout( long t )
  573.     {
  574.     return ComManipLong( sto, t );
  575.     }
  576.  
  577. static comstream& icd( comstream& o, int d )
  578.     {
  579.     o.rdbuf()->setInterCharDelay( d );
  580.     return o;
  581.     }
  582.  
  583. ComManipInt intercharDelay( int d )
  584.     {
  585.     return ComManipInt( icd, d );
  586.     }
  587.  
  588. static comstream& ild( comstream& o, int d )
  589.     {
  590.     o.rdbuf()->setInterLineDelay( d );
  591.     return o;
  592.     }
  593.  
  594. ComManipInt interlineDelay( int d )
  595.     {
  596.     return ComManipInt( ild, d );
  597.     }
  598.  
  599.